#pragma once

#include "Log.hpp"
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

namespace ns_sock
{
    class Sock
    {
    public:
        Sock() { }  // 默认构造函数
        ~Sock() { } // 析构函数

        // 创建socket文件描述符
        static int Socket()
        {
            int sock = socket(AF_INET, SOCK_STREAM, 0);
            if(sock < 0)
            {
                logMessage(FATAL, "socket error, sock:%d\n", sock);
                return -1;
            }

            logMessage(NORMAL, "socket success, sock:%d\n", sock);
            return sock;
        }

        // 绑定端口号
        static int Bind(int sock, const std::string &ip, uint16_t port)
        {
            struct sockaddr_in tmp;
            memset(&tmp, 0, sizeof(tmp));
            tmp.sin_family = AF_INET;    // 网络协议族
            tmp.sin_addr.s_addr = inet_addr(ip.c_str());  // ip地址
            tmp.sin_port = htons(port);  // 端口号
            socklen_t len = sizeof(tmp);

            if(bind(sock, (struct sockaddr *)&tmp, len) < 0)
            {
                logMessage(FATAL, "bind error!\n");
                return -1;
            }

            logMessage(NORMAL, "bind success!\n");
            return 0;
        }

        // 设置监听状态
        static int Listen(int sock, int backlog)
        {
            if(listen(sock, backlog) < 0)
            {
                logMessage(FATAL, "listen error!\n");
                return -1;
            }

            logMessage(NORMAL, "listen success!\n");
            return 0;
        }

        // 接受连接
        static int Accept(int sock, std::string *ip, uint16_t *port)
        {
            struct sockaddr_in peer;
            memset(&peer, 0, sizeof(peer));
            socklen_t len = sizeof(peer);

            int fd = accept(sock, (struct sockaddr *)&peer, &len);
            if(fd < 0) return -1;

            if(ip) *ip = inet_ntoa(peer.sin_addr);
            if(port) *port = ntohs(peer.sin_port);
            logMessage(NORMAL, "accept success, [%s-%d]\n", ip->c_str(), *port);

            return fd;
        }

        // 连接对方
        static int Connect(int sock, const std::string &ip, uint16_t port)
        {
            struct sockaddr_in peer;
            memset(&peer, 0, sizeof(peer));

            peer.sin_family = AF_INET;
            peer.sin_addr.s_addr = inet_addr(ip.c_str());
            peer.sin_port = htons(port);

            socklen_t len = sizeof(peer);

            if(connect(sock, (const struct sockaddr *)&peer, len) < 0)
            {
                logMessage(FATAL, "conect error!\n");
                return -1;
            }
            logMessage(NORMAL, "connect success!\n");

            return 0;
        }
    };
    
}